﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Lm.InferenceEngine
{
    /// <summary>
    /// 描述树形结构的节点，一个节点，就是一种可能性
    /// 此对象里包含一种“可能性”的所有状态
    /// 以及比较、判定是否成功的方法
    /// 还要能够根据当前状态，推导出下一级可能性的方法
    /// </summary>
    public abstract class InferenceObject
    {
        /// <summary>
        /// 当前节点的父节点
        /// </summary>
        public InferenceObject Parent { get; set; }
        /// <summary>
        /// 当前节点的所有子节点
        /// </summary>
        public List<InferenceObject> Childrens { get; set; }
        /// <summary>
        /// 当前节点的状态
        /// </summary>
        public InferenceStatus Status { get; set; }
        /// <summary>
        /// 与其他节点比较，判断两个节点状态是否相同
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public abstract bool SameWith(InferenceObject obj);
        /// <summary>
        /// 根据当前的状态，推导出下一级的可能性节点
        /// </summary>
        /// <returns></returns>
        public abstract List<InferenceObject> GenerateChildrens();
        /// <summary>
        /// 判断当前状态是否达到目标
        /// </summary>
        /// <returns></returns>
        public abstract bool IsSuccess();

        /// <summary>
        /// 获取所有祖先的数量，也就是当前节点到跟的路径长度
        /// </summary>
        /// <returns></returns>
        public int AncestorsCount()
        {
            return this.Count(this, 0);
        }
        /// <summary>
        /// 获取所有祖先的数量，也就是当前节点到跟的路径长度
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="count"></param>
        /// <returns></returns>
        protected int Count(InferenceObject obj, int count)
        {
            if (obj.Parent != null)
            {
                return this.Count(obj.Parent, (count + 1));
            }
            else
            {
                return count;
            }
        }

        /// <summary>
        /// 把从根到当前节点的路径，拼接成一个字符串
        /// </summary>
        /// <returns></returns>
        public string GetRoad()
        {
            var ancestorList = new List<InferenceObject>();
            this.GetRoad(this, ancestorList);
            var sb = new StringBuilder();
            for (int i = ancestorList.Count - 1; i >= 0; i--)
            {
                sb.Append(ancestorList[i].ToString() + "\r\n");
                sb.Append("===========\r\n");
            }
            return sb.ToString();
        }

        /// <summary>
        /// 获取从根到当前节点的路径上的所有节点
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="ancestorList"></param>
        protected void GetRoad(InferenceObject obj, List<InferenceObject> ancestorList)
        {
            ancestorList.Add(obj);
            if (obj.Parent != null)
            {
                this.GetRoad(obj.Parent, ancestorList);
            }
        }
    }
}
